package jaux.tank.generator.component;

import java.awt.Component;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.swing.JTabbedPane;

import jaux.tank.generator.domain.TankApplication;
import jaux.tank.generator.domain.TankConstant;
import jaux.tank.generator.domain.TankEntity;
import jaux.tank.generator.domain.TankEntityRelationship;
import jaux.tank.generator.domain.TankEnum;
import jaux.tank.generator.domain.TankRoot;

public class TankTabbedPane extends JTabbedPane {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private TankGeneratorFrame tankFrame;
	
	public TankTabbedPane(TankGeneratorFrame tankFrame) {
		super();
		this.tankFrame = tankFrame;
		initComponents();
	}
	
	private void initComponents() {
		setMinimumSize(new Dimension(650, 0));
	}
	public void openApplicationTab(TankApplication app, boolean newApp) {
		int tabCount = this.getTabCount();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = this.getComponentAt(i);
			if(tabComp instanceof ApplicationEditorPanel) {
				ApplicationEditorPanel appEditor = (ApplicationEditorPanel)tabComp;
				if(app.getId().equals(appEditor.getApplication().getId())) {
					this.setSelectedIndex(i);
					return;
				}
			}
		}
		ApplicationEditorPanel appEditor = new ApplicationEditorPanel(app);
		appEditor.setSaved(!newApp);
		this.addTab(tankFrame.getString("application")+" - "+app.getName(), appEditor);
		this.setSelectedIndex(tabCount);
	}
	
	public void openEntityTab(TankEntity entity, boolean newEntity) {
		int tabCount = this.getTabCount();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = this.getComponentAt(i);
			if(tabComp instanceof EntityEditorPanel) {
				EntityEditorPanel entityEditor = (EntityEditorPanel)tabComp;
				if(entity.getId().equals(entityEditor.getEntity().getId())) {
					this.setSelectedIndex(i);
					return;
				}
			}
		}
		EntityEditorPanel entityEditor = new EntityEditorPanel(entity, ()->tankFrame.getTankRoot().getEnums());
		entityEditor.setSaved(!newEntity);
		this.addTab(tankFrame.getString("entity")+" - "+entity.getName(), entityEditor);
		this.setSelectedIndex(tabCount);
	}
	
	public void openRelationshipTab(TankEntityRelationship relationship, boolean newRelationship) {
		int tabCount = this.getTabCount();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = this.getComponentAt(i);
			if(tabComp instanceof RelationshipEditorPanel) {
				RelationshipEditorPanel relationshipEditor = (RelationshipEditorPanel)tabComp;
				if(relationship.getId().equals(relationshipEditor.getRelationship().getId())) {
					this.setSelectedIndex(i);
					return;
				}
			}
		}
		RelationshipEditorPanel relationshipEditor = new RelationshipEditorPanel(relationship,()->tankFrame.getTankRoot().getEntities());
		relationshipEditor.setSaved(!newRelationship);
		this.addTab(tankFrame.getString("relationship")+" - "+relationship.getName(), relationshipEditor);
		this.setSelectedIndex(tabCount);
	}
	
	public void openEnumTab(TankEnum tankEnum, boolean newEnum) {
		int tabCount = this.getTabCount();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = this.getComponentAt(i);
			if(tabComp instanceof EnumEditorPanel) {
				EnumEditorPanel enumEditor = (EnumEditorPanel)tabComp;
				if(tankEnum.getName().equals(enumEditor.getTankEnum().getName())) {
					this.setSelectedIndex(i);
					return;
				}
			}
		}
		EnumEditorPanel enumEditor = new EnumEditorPanel(tankEnum);
		enumEditor.setSaved(!newEnum);
		this.addTab(tankFrame.getString("enum")+" - "+tankEnum.getName(), enumEditor);
		this.setSelectedIndex(tabCount);
	}
	
	public void openConstantTab(TankConstant constant, boolean newConstant) {
		// check already opened
		for (int i = 0; i < this.getTabCount(); i++) {
			Component tabComp = this.getComponentAt(i);
			if (tabComp instanceof ConstantEditorPanel) {
				ConstantEditorPanel constantEditor = (ConstantEditorPanel) tabComp;
				if(constantEditor.getConstant().getName().equals(constant.getName())) {
					this.setSelectedComponent(tabComp);
					return;
				}
			}
		}
		ConstantEditorPanel constantEditor = new ConstantEditorPanel(constant );
		constantEditor.setSaved(!newConstant);
		this.add(tankFrame.getString("constant") +" - "+constant.getName(), constantEditor);
		this.setSelectedIndex( this.getTabCount()-1);
	}

	public void refresh() {
		int tabCount = this.getTabCount();
		// remove deleted objects
		List<Component> deletedTabs = new ArrayList<>();
		TankRoot tankRoot = tankFrame.getTankRoot();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = this.getComponentAt(i);
			if(tabComp instanceof ApplicationEditorPanel) {
				ApplicationEditorPanel appEditor = (ApplicationEditorPanel)tabComp;
				boolean appExists = tankRoot.getApplications().stream().anyMatch(app->app.getId().equals(appEditor.getApplication().getId()));
				if(!appExists) {
					deletedTabs.add(tabComp);
				}
			}else if(tabComp instanceof EntityEditorPanel) {
				EntityEditorPanel entityEditor = (EntityEditorPanel)tabComp;
				boolean entityExists = tankRoot.getEntities().stream().anyMatch(entity->entity.getId().equals(entityEditor.getEntity().getId()));
				if(!entityExists) {
					deletedTabs.add(tabComp);
				}
			}else if(tabComp instanceof RelationshipEditorPanel) {
				RelationshipEditorPanel relationshipEditor = (RelationshipEditorPanel)tabComp;
				boolean relationshipExists = tankRoot.getRelationships().stream().anyMatch(relationship->relationship.getId().equals(relationshipEditor.getRelationship().getId()));
				if(!relationshipExists) {
					deletedTabs.add(tabComp);
				}
			}else if(tabComp instanceof EnumEditorPanel) {
				EnumEditorPanel enumEditor = (EnumEditorPanel)tabComp;
				boolean enumExists = tankRoot.getEnums().stream().anyMatch(tankEnum->tankEnum.getName().equals(enumEditor.getTankEnum().getName()));
				if(!enumExists) {
					deletedTabs.add(tabComp);
				}
			}else if(tabComp instanceof ConstantEditorPanel) {
				ConstantEditorPanel constantEditor = (ConstantEditorPanel)tabComp;
				boolean constantExists = tankRoot.getConstants().stream().anyMatch(tankConstant->tankConstant.getName().equals(constantEditor.getConstant().getName()));
				if(!constantExists) {
					deletedTabs.add(tabComp);
				}
			}
		}
		deletedTabs.forEach(tab->this.remove(tab));
		
	}
	
	public List<TankApplication> getAllApplications(){
		int tabCount = getTabCount();
		List<TankApplication> applications = new ArrayList<>();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = getComponentAt(i);
			if(tabComp instanceof ApplicationEditorPanel) {
				ApplicationEditorPanel appEditor = (ApplicationEditorPanel)tabComp;
				applications.add(appEditor.getApplication());
			}
		}
		return applications;
	}
	
	public List<TankEntity> getAllEntities(){
		int tabCount = getTabCount();
		List<TankEntity> entities = new ArrayList<>();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = getComponentAt(i);
			if(tabComp instanceof EntityEditorPanel) {
				EntityEditorPanel entityEditor = (EntityEditorPanel)tabComp;
				entities.add(entityEditor.getEntity());
			}
		}
		return entities;
	}
	
	public List<TankEntityRelationship> getAllRelationships(){
		int tabCount = getTabCount();
		List<TankEntityRelationship> relationships = new ArrayList<>();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = getComponentAt(i);
			if(tabComp instanceof RelationshipEditorPanel) {
				RelationshipEditorPanel relationshipEditor = (RelationshipEditorPanel)tabComp;
				relationships.add(relationshipEditor.getRelationship());
			}
		}
		return relationships;
	}
	
	/**
	 * get all enums
	 * @return all enums
	 */
	public List<TankEnum> getAllEnums(){
		int tabCount = getTabCount();
		List<TankEnum> enums = new ArrayList<>();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = getComponentAt(i);
			if(tabComp instanceof EnumEditorPanel) {
				EnumEditorPanel enumEditor = (EnumEditorPanel)tabComp;
				enums.add(enumEditor.getTankEnum());
			}
		}
		return enums;
	}
	
	/**
	 * get all constants
	 * @return all constants
	 */
	public List<TankConstant> getAllConstants(){
		int tabCount = getTabCount();
		List<TankConstant> constants = new ArrayList<>();
		for(int i=0;i<tabCount;i++) {
			Component tabComp = getComponentAt(i);
			if(tabComp instanceof ConstantEditorPanel) {
				ConstantEditorPanel constantEditor = (ConstantEditorPanel)tabComp;
				constants.add(constantEditor.getConstant());
			}
		}
		return constants;
	}
	
	public boolean isAllEditorSaved() {
		for (int i = 0; i < this.getTabCount(); i++) {
			Component tabComp = this.getComponentAt(i);
			if (tabComp instanceof ApplicationEditorPanel) {
				ApplicationEditorPanel appEditor = (ApplicationEditorPanel) tabComp;
				if(!appEditor.isSaved()) {
					return false;
				}
			}else if(tabComp instanceof EntityEditorPanel) {
				EntityEditorPanel entityEditor = (EntityEditorPanel) tabComp;
				if(!entityEditor.isSaved()) {
					return false;
				}
			}else if(tabComp instanceof RelationshipEditorPanel) {
				RelationshipEditorPanel relationshipEditor = (RelationshipEditorPanel) tabComp;
				if(!relationshipEditor.isSaved()) {
					return false;
				}
			}else if(tabComp instanceof EnumEditorPanel) {
				EnumEditorPanel enumEditor = (EnumEditorPanel) tabComp;
				if(!enumEditor.isSaved()) {
					return false;
				}
			}else if(tabComp instanceof ConstantEditorPanel) {
				ConstantEditorPanel constantEditor = (ConstantEditorPanel) tabComp;
				if(!constantEditor.isSaved()) {
					return false;
				}
			}
		}
		return true;
	}
	void setAllEditorSaved(boolean saved) {
		for (int i = 0; i < this.getTabCount(); i++) {
			Component tabComp = this.getComponentAt(i);
			if (tabComp instanceof ApplicationEditorPanel) {
				ApplicationEditorPanel appEditor = (ApplicationEditorPanel) tabComp;
				appEditor.setSaved(saved);
			}else if(tabComp instanceof EntityEditorPanel) {
				EntityEditorPanel entityEditor = (EntityEditorPanel) tabComp;
				entityEditor.setSaved(saved);
			}else if(tabComp instanceof RelationshipEditorPanel) {
				RelationshipEditorPanel relationshipEditor = (RelationshipEditorPanel) tabComp;
				relationshipEditor.setSaved(saved);
			}else if(tabComp instanceof EnumEditorPanel) {
				EnumEditorPanel enumEditor = (EnumEditorPanel) tabComp;
				enumEditor.setSaved(saved);
			}else if(tabComp instanceof ConstantEditorPanel) {
				ConstantEditorPanel constantEditor = (ConstantEditorPanel) tabComp;
				constantEditor.setSaved(saved);
			}
		}
	}
}
